package com.niiwoo.civet.trade.service.dubbo.creditor;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.niiwoo.civet.trade.dao.entity.CreditorRateConfig;
import com.niiwoo.civet.trade.dao.entity.Project;
import com.niiwoo.civet.trade.dao.entity.ProjectInvestOrder;
import com.niiwoo.civet.trade.dao.mapper.InvestorCreditorMapperExt;
import com.niiwoo.civet.trade.dao.mapper.ProjectInvestOrderMapperExt;
import com.niiwoo.civet.trade.dto.CreditorSaleOrderRateAreaDTO;
import com.niiwoo.civet.trade.dto.request.creditor.InvestOrderTradableValidateRequestDTO;
import com.niiwoo.civet.trade.dto.request.creditor.TradableInvestOrderRequestDTO;
import com.niiwoo.civet.trade.dto.response.creditor.InvestOrderTradableValidateResponseDTO;
import com.niiwoo.civet.trade.dto.response.creditor.PageTradableInvestOrderDTO;
import com.niiwoo.civet.trade.dto.response.creditor.TradableInvestOrderDTO;
import com.niiwoo.civet.trade.dto.response.creditor.TradableInvestOrderStatDTO;
import com.niiwoo.civet.trade.enums.TradeConfigEnum;
import com.niiwoo.civet.trade.service.creditor.TradableInvestOrderDubboService;
import com.niiwoo.civet.trade.service.local.creditor.CreditorRateConfigService;
import com.niiwoo.civet.trade.service.local.creditor.CreditorSaleOrderService;
import com.niiwoo.civet.trade.service.local.creditor.TradableInvestOrderService;
import com.niiwoo.civet.trade.service.local.project.ProjectLocalService;
import com.niiwoo.tripod.provider.exception.BizException;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service(version = "1.0.0")
public class TradableInvestOrderDubboServiceImpl implements TradableInvestOrderDubboService {

	@Autowired
	private InvestorCreditorMapperExt investorCreditorMapperExt;
	
	@Autowired
	private ProjectInvestOrderMapperExt projectInvestOrderMapperExt;
	
	@Autowired
	private ProjectLocalService projectLocalService;
	
	@Autowired
	private CreditorRateConfigService creditorRateConfigService;
	
	@Autowired
	private CreditorSaleOrderService creditorSaleOrderService;
	
	@Autowired
	private TradableInvestOrderService tradableInvestOrderService;
	
	public PageTradableInvestOrderDTO getAllTradableInvestOrders(TradableInvestOrderRequestDTO request) {
		// 封装条件
		tradableInvestOrderService.buildTradableInvestOrderQueryCondition(request);
		
		PageHelper.startPage(request.getPageNumber(), request.getPageSize());
        List<TradableInvestOrderDTO> list = investorCreditorMapperExt.getAllTradableInvestOrdersByPage(request);
        PageInfo<TradableInvestOrderDTO> pageInfo = new PageInfo(list);
		
		if (list != null && !list.isEmpty()) {
			Project project = null;
			ProjectInvestOrder projectInvestOrder = null;
			CreditorRateConfig rc = null;
			for (TradableInvestOrderDTO dto : list) {
				project = projectLocalService.selectByUserIdAndProjectId(request.getUserId(), dto.getProjectId());
				
				if (project != null) dto.setBorrowRate(project.getBorrowRate());
				// 通过投资订单ID获取t_tc_project_invest_order.creditor_sale_user_id
				projectInvestOrder = projectInvestOrderMapperExt.selectByPrimaryKey(dto.getInvestOrderId());
				if (projectInvestOrder != null && projectInvestOrder.getCreditorSaleUserId() != null) {
					dto.setBorrowUserId(projectInvestOrder.getCreditorSaleUserId());
				}
				
				//总本金-已收本金+当期应收利息
				if (dto.getReceivableInterest().compareTo(new BigDecimal(0)) < 0) dto.setReceivableInterest(new BigDecimal(0)); //防止数据库计算为负数，不会出现
				
				dto.setAmount(dto.getCapital().subtract(dto.getReceivedCapital()).add(dto.getReceivableInterest()).setScale(2, RoundingMode.HALF_EVEN));
				dto.setTradableAmount(dto.getAmount());
				dto.setRemainDay(tradableInvestOrderService.calcCurrentPriodRemainDays(dto.getReceivedDate(), dto.getLastPeriodReceivedDate(), dto.getProjectId()));
				dto.setRemainDay(dto.getRemainDay() + 1); //发起债转的日期需要给到受让人
				dto.setRemainMonth(dto.getDeadline() - dto.getCurrentPeriod());
				
				//设置转让费率
				rc = creditorRateConfigService.getCreditorRateConfigService(dto.getReceivedPeriod(), dto.getRepaymentType());
				if (rc != null)
        			dto.setTradeFeeRate(rc.getTransferRate());
				else 
					log.error("转让费率配置不存在，投资订单ID={}", dto.getInvestOrderId());
			}
		}
		
		PageTradableInvestOrderDTO result = new PageTradableInvestOrderDTO();
		result.setItems(list);
		result.setTotalCount((int) pageInfo.getTotal());
		result.setTotalPage(pageInfo.getPages());
		
        Map<String, String> map = tradableInvestOrderService.getTradableInvestOrderLimitCondition();
        Integer maxTradingNum = 0;
        if (map != null && map.containsKey(TradeConfigEnum.DEBT_MAX_TRANSFER_COUNT.getConfigKey())) {
        	maxTradingNum = Integer.valueOf(map.get(TradeConfigEnum.DEBT_MAX_TRANSFER_COUNT.getConfigKey()));
        }
		// 获取当前转让中状态债权数量
		Integer tradingNum = creditorSaleOrderService.getTradingCreditorSaleDetailNum(request.getUserId());
		
		result.setMaxSelect(maxTradingNum == 0 ? maxTradingNum : maxTradingNum - tradingNum);
		
		return result;
	}

	@Override
	public TradableInvestOrderStatDTO getTradableInvestOrderStat(String userId) {
		// 判断是否开启债权转让
        Map<String, String> map = tradableInvestOrderService.getTradableInvestOrderLimitCondition();
        if (map != null) {
    		String debtOnOff = MapUtils.getString(map, TradeConfigEnum.DEBT_ON_OFF.getConfigKey(), "0");
    		String debtBusOnOff = MapUtils.getString(map, TradeConfigEnum.DEBT_LAUNCH_ON_OFF.getConfigKey(), "0");
    		if ("0".equals(debtOnOff) || "0".equals(debtBusOnOff)) {
    			throw new BizException("TRD1000001");
    		}
        }
		
		TradableInvestOrderRequestDTO request = new TradableInvestOrderRequestDTO();
		request.setUserId(userId);
		
		// 封装条件
		tradableInvestOrderService.buildTradableInvestOrderQueryCondition(request);
		
		TradableInvestOrderStatDTO dto = null;
		
//		TradableInvestOrderStatDTO dto = investorCreditorMapperExt.getTradableInvestOrderStat(request);
//		if (dto == null || dto.getAmount() == null || dto.getOrderNums() == 0) {
//			dto = new TradableInvestOrderStatDTO();
//		}
		
		List<TradableInvestOrderStatDTO> list = investorCreditorMapperExt.getAllTradableInvestorCreditor(request);
		if (list == null || list.isEmpty()) {
			dto = new TradableInvestOrderStatDTO();
		} else {
			// 可转让总金额
			BigDecimal totalAmount = new BigDecimal(0);
			// 待收本金
			BigDecimal amount = new BigDecimal(0);
			// 应收利息
			BigDecimal receivableInterest = new BigDecimal(0); 
			for (TradableInvestOrderStatDTO item : list) {
				// totalAmount = totalAmount.add(item.getAmount().add(item.getReceivableInterest()).setScale(2, RoundingMode.HALF_EVEN));
				amount = amount.add(item.getAmount().setScale(2, RoundingMode.HALF_EVEN));
				
				if (receivableInterest.compareTo(new BigDecimal(0)) < 0) item.setReceivableInterest(new BigDecimal(0)); //防止数据库计算为负数，不会出现
				receivableInterest = receivableInterest.add(item.getReceivableInterest().setScale(2, RoundingMode.HALF_EVEN));
			}
			
			dto = new TradableInvestOrderStatDTO();
			dto.setAmount(amount);
			dto.setReceivableInterest(receivableInterest);
			dto.setOrderNums(list.size());
		}
		
		dto.setTotalAmount(dto.getAmount().add(dto.getReceivableInterest()).setScale(2, RoundingMode.HALF_EVEN));
		dto.setInterest(dto.getReceivableInterest());
		
		CreditorSaleOrderRateAreaDTO rateConfig = creditorRateConfigService.getCreditorSaleOrderRateArea();
		if (rateConfig != null) {
			dto.setMaxFeeRate(rateConfig.getMaxRate());
			dto.setMinFeeRate(rateConfig.getMinRate());
		} else {
			throw new BizException("TRD1000007");
		}
		return dto;
	}

	@Override
	public TradableInvestOrderDTO getTradableInvestOrder(String userId, Long investOrderId) {
		TradableInvestOrderRequestDTO request = new TradableInvestOrderRequestDTO();
		request.setUserId(userId);
		request.setInvestOrderId(investOrderId);
		
		// 封装条件
		tradableInvestOrderService.buildTradableInvestOrderQueryCondition(request);
		
		TradableInvestOrderDTO dto = investorCreditorMapperExt.getTradableInvestOrder(request);
		
		if (dto == null) {
			log.error("投资订单不存在，订单ID={}", investOrderId);
			return null;
		}
		
		Project project = projectLocalService.selectByUserIdAndProjectId(request.getUserId(), dto.getProjectId());
		if (project != null) {
			dto.setBorrowRate(project.getBorrowRate());
		}
		
		// 通过投资订单ID获取t_tc_project_invest_order.creditor_sale_user_id
		ProjectInvestOrder projectInvestOrder = projectInvestOrderMapperExt.selectByPrimaryKey(dto.getInvestOrderId());
		if (projectInvestOrder != null && projectInvestOrder.getCreditorSaleUserId() != null) {
			dto.setBorrowUserId(projectInvestOrder.getCreditorSaleUserId());
		}
		
		if (dto.getReceivableInterest().compareTo(new BigDecimal(0)) < 0) dto.setReceivableInterest(new BigDecimal(0)); //防止数据库计算为负数，不会出现
		
		if (dto.getReceivedCapital() == null) dto.setReceivedCapital(new BigDecimal(0));
		if (dto.getReceivableInterest() == null) dto.setReceivableInterest(new BigDecimal(0));
		
		//总本金-已收本金+当期应收利息
		dto.setAmount(dto.getCapital().subtract(dto.getReceivedCapital()).add(dto.getReceivableInterest()).setScale(2, RoundingMode.HALF_EVEN));
		dto.setTradableAmount(dto.getAmount());
		dto.setRemainDay(tradableInvestOrderService.calcCurrentPriodRemainDays(dto.getReceivedDate(), dto.getLastPeriodReceivedDate(), dto.getProjectId()));
		dto.setRemainDay(dto.getRemainDay() + 1); //发起债转的日期需要给到受让人
		dto.setRemainMonth(dto.getDeadline() - dto.getCurrentPeriod());
		
		//设置转让费率
		CreditorRateConfig rc = creditorRateConfigService.getCreditorRateConfigService(dto.getReceivedPeriod(), dto.getRepaymentType());
		if (rc != null)
			dto.setTradeFeeRate(rc.getTransferRate());
		else {
			throw new BizException("TRD1000007");
		}
		
		return dto;
	}

	@Override
	public InvestOrderTradableValidateResponseDTO investOrderTradableValidate(InvestOrderTradableValidateRequestDTO request) {
		Assert.notNull(request, "参数对象不可空");
		Assert.notEmpty(request.getInvestOrderIds(), "未选择可转让债权");
		
		String userId = request.getUserId();
		
		// 债权转让是否开启，当前时间是否在可操作范围之内
		tradableInvestOrderService.validateGlobalConfiguration();
		
		Map<String, String> configs = tradableInvestOrderService.getTradableInvestOrderLimitCondition();
		String creditorQualificationPromptText = MapUtils.getString(configs, TradeConfigEnum.CREDITOR_QUALIFICATION_PROMPT_TEXT.getConfigKey(), "");
		
		TradableInvestOrderRequestDTO condition = new TradableInvestOrderRequestDTO();
		condition.setUserId(userId);
		condition.setInvestOrderIds(request.getInvestOrderIds());
		
		// 封装条件
		tradableInvestOrderService.buildTradableInvestOrderQueryCondition(condition);
		
		List<TradableInvestOrderDTO> investorCreditorList = investorCreditorMapperExt.investOrderTradableValidate(condition);
		if (investorCreditorList == null || request.getInvestOrderIds().size() != investorCreditorList.size()) {
			log.error("###债权出让申请###批量转让申请个数与实际可转让个数不一致,UserId:{}", userId);
			// 防止后台配置的时候直接存在换行符
			if (creditorQualificationPromptText.contains("\n")) creditorQualificationPromptText = creditorQualificationPromptText.replaceAll("\n", "");
			if (creditorQualificationPromptText.contains("\r")) creditorQualificationPromptText = creditorQualificationPromptText.replaceAll("\r", "");
			creditorQualificationPromptText = "\n" + creditorQualificationPromptText; //xml中会将换行符\n转成字符串导致前端无法实现换行
			throw new BizException("TRD1000006", creditorQualificationPromptText.replaceAll("\\|", "\n"));
		}
		
		InvestOrderTradableValidateResponseDTO result = new InvestOrderTradableValidateResponseDTO();
		result.setIsTradable(1);
		
		return result;
	}

}